const http = require('http');
const { spawn } = require('child_process');
const url = require('url');
const dotenv = require('dotenv');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

// 加载环境变量配置
dotenv.config();

// 从环境变量获取配置，提供默认值
const RTMP_SERVER = process.env.RTMP_SERVER || '192.168.22.180';
const RTMP_PORT = process.env.RTMP_PORT || '1935';
const LOG_DIR = process.env.LOG_DIR || './logs';
const SERVER_PORT = process.env.SERVER_PORT || 8081;

// 创建日志目录
if (!fs.existsSync(LOG_DIR)) {
  fs.mkdirSync(LOG_DIR, { recursive: true });
}

// 存储RTSP流与ffmpeg进程的映射
const streamProcessMap = new Map();

// 流状态枚举
const STREAM_STATUS = {
  RUNNING: 'running',
  STOPPED: 'stopped',
  ERROR: 'error'
};

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  // 解析请求URL
  const parsedUrl = url.parse(req.url, true);
  const pathname = parsedUrl.pathname;
  const query = parsedUrl.query;
  const { method } = req;

  // 设置默认响应头
  res.setHeader('Content-Type', 'application/json');
  
  // 检查是否为直播代理请求
  if (method === 'GET' && pathname.startsWith('/live/') && pathname.endsWith('.flv') && query.src) {
    handleStreamRequest(req, res, query.src, pathname);
    return;
  }
  
  // 处理流控制请求
  if (method === 'POST' && pathname === '/api/stream/start') {
    handleStartStreamRequest(req, res, query);
    return;
  }
  
  if (method === 'POST' && pathname === '/api/stream/stop') {
    handleStopStreamRequest(req, res, query);
    return;
  }
  
  // 获取流列表
  if (method === 'GET' && pathname === '/api/streams') {
    handleGetStreamsRequest(req, res);
    return;
  }
  
  // 获取服务器状态
  if (method === 'GET' && pathname === '/api/status') {
    handleGetStatusRequest(req, res);
    return;
  }
  
  // 未知路径
  res.statusCode = 404;
  res.end(JSON.stringify({
    success: false,
    message: '未找到资源'
  }));
});

// 处理流启动请求
function handleStreamRequest(req, res, rtspUrl, pathname) {
  try {
    // 验证RTSP URL
    if (!isValidRtspUrl(rtspUrl)) {
      res.statusCode = 400;
      res.end(JSON.stringify({
        success: false,
        message: '无效的RTSP URL'
      }));
      return;
    }
    
    const streamKey = pathname.split('/').pop();
    const streamId = streamKey.replace(/\.flv$/, '');
    
    // 验证流ID
    if (!isValidStreamId(streamId)) {
      res.statusCode = 400;
      res.end(JSON.stringify({
        success: false,
        message: '无效的流ID，只能包含字母、数字、下划线和连字符'
      }));
      return;
    }
    
    const rtmpUrl = `rtmp://${RTMP_SERVER}:${RTMP_PORT}${pathname}`;

    console.log(`收到流启动请求: ${rtspUrl} 转推至 ${rtmpUrl}`);

    // 检查流是否已在处理中
    if (streamProcessMap.has(rtspUrl)) {
      console.log(`流 ${rtspUrl} 已在处理中`);
      res.statusCode = 200;
      res.end(JSON.stringify({
        success: true,
        message: `流 ${streamId} 已在运行`,
        data: {
          streamId,
          status: STREAM_STATUS.RUNNING,
          startTime: streamProcessMap.get(rtspUrl).startTime.toISOString()
        }
      }));
      return;
    }

    // 创建日志文件
    const logFile = path.join(LOG_DIR, `${streamId}_${Date.now()}.log`);
    
    // 显式打开文件描述符
    let stdoutFd, stderrFd;
    try {
      stdoutFd = fs.openSync(logFile, 'a');
      stderrFd = fs.openSync(logFile, 'a');
    } catch (err) {
      console.error(`无法打开日志文件: ${err.message}`);
      res.statusCode = 500;
      res.end(JSON.stringify({
        success: false,
        message: `无法打开日志文件: ${err.message}`
      }));
      return;
    }

    // 构建ffmpeg命令参数
    const ffmpegArgs = [
      '-rtsp_transport', 'tcp',
      '-timeout', '10000000',
      '-i', rtspUrl,
      '-codec', 'copy',
      '-f', 'flv',
      rtmpUrl
    ];

    // 启动ffmpeg进程（使用detached模式在后台运行）
    const ffmpegProcess = spawn('ffmpeg', ffmpegArgs, {
      detached: true,
      stdio: ['ignore', stdoutFd, stderrFd] // 使用文件描述符而非流对象
    });

    // 记录流与进程的映射
    streamProcessMap.set(rtspUrl, {
      process: ffmpegProcess,
      command: `ffmpeg ${ffmpegArgs.join(' ')}`,
      startTime: new Date(),
      logFile,
      fileDescriptors: { stdout: stdoutFd, stderr: stderrFd },
      streamId,
      status: STREAM_STATUS.RUNNING
    });

    // 从父进程分离
    ffmpegProcess.unref();

    // 监听ffmpeg进程退出事件
    ffmpegProcess.on('close', (code) => {
      console.log(`流 ${rtspUrl} (${streamId}) 的ffmpeg进程已退出，退出码: ${code}`);
      
      // 更新流状态
      const streamInfo = streamProcessMap.get(rtspUrl);
      if (streamInfo) {
        streamInfo.status = STREAM_STATUS.STOPPED;
        
        // 关闭文件描述符
        fs.closeSync(streamInfo.fileDescriptors.stdout);
        fs.closeSync(streamInfo.fileDescriptors.stderr);
        
        streamProcessMap.delete(rtspUrl);
      }
    });

    // 监听ffmpeg进程错误事件
    ffmpegProcess.on('error', (err) => {
      console.error(`执行ffmpeg时出错: ${err.message}`);
      
      // 更新流状态
      const streamInfo = streamProcessMap.get(rtspUrl);
      if (streamInfo) {
        streamInfo.status = STREAM_STATUS.ERROR;
        
        // 关闭文件描述符
        fs.closeSync(streamInfo.fileDescriptors.stdout);
        fs.closeSync(streamInfo.fileDescriptors.stderr);
        
        streamProcessMap.delete(rtspUrl);
      }
    });

    res.statusCode = 200;
    res.end(JSON.stringify({
      success: true,
      message: `成功启动流 ${streamId}`,
      data: {
        streamId,
        rtspUrl,
        rtmpUrl,
        status: STREAM_STATUS.RUNNING,
        startTime: new Date().toISOString(),
        logFile
      }
    }));
  } catch (err) {
    console.error(`处理流请求时出错: ${err.message}`);
    res.statusCode = 500;
    res.end(JSON.stringify({
      success: false,
      message: `服务器内部错误: ${err.message}`
    }));
  }
}

// 处理API启动流请求
function handleStartStreamRequest(req, res, query) {
  const { rtspUrl, streamId } = query;
  
  if (!rtspUrl || !streamId) {
    res.statusCode = 400;
    res.end(JSON.stringify({
      success: false,
      message: '缺少必要参数: rtspUrl 或 streamId'
    }));
    return;
  }
  
  const pathname = `/live/${streamId}.flv`;
  handleStreamRequest(req, res, rtspUrl, pathname);
}

// 处理API停止流请求
function handleStopStreamRequest(req, res, query) {
  const { streamId } = query;
  
  if (!streamId) {
    res.statusCode = 400;
    res.end(JSON.stringify({
      success: false,
      message: '缺少必要参数: streamId'
    }));
    return;
  }
  
  try {
    let stopped = false;
    let errorMessage = '';
    
    // 查找匹配的流
    for (const [rtspUrl, streamInfo] of streamProcessMap.entries()) {
      if (streamInfo.streamId === streamId) {
        try {
          console.log(`收到停止流请求: ${streamId}`);
          
          // 终止进程
          process.kill(-streamInfo.process.pid);
          
          // 关闭文件描述符
          fs.closeSync(streamInfo.fileDescriptors.stdout);
          fs.closeSync(streamInfo.fileDescriptors.stderr);
          
          streamProcessMap.delete(rtspUrl);
          stopped = true;
          
          console.log(`流 ${streamId} 已成功停止`);
          break;
        } catch (err) {
          console.error(`停止流 ${streamId} 失败: ${err.message}`);
          errorMessage = err.message;
        }
      }
    }
    
    if (stopped) {
      res.statusCode = 200;
      res.end(JSON.stringify({
        success: true,
        message: `流 ${streamId} 已成功停止`
      }));
    } else {
      res.statusCode = 404;
      res.end(JSON.stringify({
        success: false,
        message: `未找到流: ${streamId}`,
        error: errorMessage
      }));
    }
  } catch (err) {
    console.error(`处理停止流请求时出错: ${err.message}`);
    res.statusCode = 500;
    res.end(JSON.stringify({
      success: false,
      message: `服务器内部错误: ${err.message}`
    }));
  }
}

// 处理获取流列表请求
function handleGetStreamsRequest(req, res) {
  try {
    const streams = Array.from(streamProcessMap.entries()).map(([rtspUrl, streamInfo]) => ({
      streamId: streamInfo.streamId,
      rtspUrl,
      rtmpUrl: `rtmp://${RTMP_SERVER}:${RTMP_PORT}/live/${streamInfo.streamId}.flv`,
      status: streamInfo.status,
      pid: streamInfo.process.pid,
      startTime: streamInfo.startTime.toISOString(),
      runningTime: Math.floor((Date.now() - streamInfo.startTime) / 1000), // 秒
      logFile: streamInfo.logFile
    }));
    
    res.statusCode = 200;
    res.end(JSON.stringify({
      success: true,
      message: '获取流列表成功',
      data: {
        total: streams.length,
        streams
      }
    }));
  } catch (err) {
    console.error(`处理获取流列表请求时出错: ${err.message}`);
    res.statusCode = 500;
    res.end(JSON.stringify({
      success: false,
      message: `服务器内部错误: ${err.message}`
    }));
  }
}

// 处理获取服务器状态请求
function handleGetStatusRequest(req, res) {
  try {
    const status = {
      serverTime: new Date().toISOString(),
      uptime: process.uptime(), // 秒
      activeStreams: streamProcessMap.size,
      memoryUsage: process.memoryUsage(),
      config: {
        RTMP_SERVER,
        RTMP_PORT,
        LOG_DIR,
        SERVER_PORT
      }
    };
    
    res.statusCode = 200;
    res.end(JSON.stringify({
      success: true,
      message: '获取服务器状态成功',
      data: status
    }));
  } catch (err) {
    console.error(`处理获取服务器状态请求时出错: ${err.message}`);
    res.statusCode = 500;
    res.end(JSON.stringify({
      success: false,
      message: `服务器内部错误: ${err.message}`
    }));
  }
}

// 验证RTSP URL
function isValidRtspUrl(url) {
  const rtspRegex = /^rtsp:\/\/.+$/i;
  return rtspRegex.test(url);
}

// 验证流ID
function isValidStreamId(id) {
  const streamIdRegex = /^[a-zA-Z0-9_-]+$/;
  return streamIdRegex.test(id);
}

// 启动服务器
server.listen(SERVER_PORT, '0.0.0.0', () => {
  console.log(`服务器运行在 http://0.0.0.0:${SERVER_PORT}/`);
  console.log(`RTMP目标服务器: ${RTMP_SERVER}:${RTMP_PORT}`);
  console.log(`日志目录: ${LOG_DIR}`);
});

// 添加优雅关闭逻辑
process.on('SIGINT', () => {
  console.log('正在关闭服务器...');
  
  // 终止所有ffmpeg进程并关闭文件描述符
  streamProcessMap.forEach((value, key) => {
    console.log(`终止流 ${value.streamId} 的ffmpeg进程`);
    try {
      process.kill(-value.process.pid); // 终止整个进程组
      fs.closeSync(value.fileDescriptors.stdout);
      fs.closeSync(value.fileDescriptors.stderr);
    } catch (err) {
      console.error(`无法终止进程 ${value.process.pid} 或关闭文件描述符: ${err.message}`);
    }
  });
  
  server.close(() => {
    console.log('服务器已关闭');
    process.exit(0);
  });
});

// 添加简单的进程监控（每5分钟检查一次）
setInterval(() => {
  console.log(`当前活跃流数量: ${streamProcessMap.size}`);
  
  if (streamProcessMap.size > 0) {
    console.log('活跃流列表:');
    streamProcessMap.forEach((value, key) => {
      console.log(`- ${value.streamId}: ${key} (PID: ${value.process.pid}, 运行时间: ${Math.round((new Date() - value.startTime) / 60000)} 分钟)`);
    });
  }
}, 300000);

// 添加系统错误处理
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的Promise拒绝:', reason);
});

process.on('uncaughtException', (err) => {
  console.error('未捕获的异常:', err);
  // 可以选择优雅地关闭服务器
  // server.close(() => process.exit(1));
});
